package org.budo.weixin.work.api.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.budo.support.lang.util.StringUtil;
import org.budo.xml.Xml;
import org.budo.xml.XmlObject;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

/**
 * @author lmw
 */
@Getter
@Setter
@ToString
@NoArgsConstructor
@Slf4j
public class ApprovalWebhookImpl implements ApprovalDetail, Serializable {
    private static final long serialVersionUID = -6408381538285065727L;

    private String xml;

    public ApprovalWebhookImpl(String xml) {
        this.xml = xml;
    }

    @Override
    public String getRequestBody() {
        return this.xml;
    }

    @Override
    public String getApplyerUserId() {
        XmlObject approvalInfo = this.approvalInfo();
        XmlObject applyer = approvalInfo.getChildNodeByName("Applyer");
        return applyer.getChildNodeTextContentByName("UserId");
    }

    @Override
    public String getSpNo() {
        XmlObject approvalInfo = this.approvalInfo();

        return approvalInfo.getChildNodeTextContentByName("SpNo");
    }

    @Override
    public String getSpName() {
        XmlObject approvalInfo = this.approvalInfo();

        return approvalInfo.getChildNodeTextContentByName("SpName");
    }

    @Override
    public String getTemplateId() {
        XmlObject approvalInfo = this.approvalInfo();

        return approvalInfo.getChildNodeTextContentByName("TemplateId");
    }

    /**
     * 申请单状态：1-审批中；2-已通过；3-已驳回；4-已撤销；6-通过后撤销；7-已删除；10-已支付
     */
    public String getSpStatus() {
        XmlObject approvalInfo = this.approvalInfo();

        return approvalInfo.getChildNodeTextContentByName("SpStatus");
    }

    // 审批申请状态变化类型：1-提单；2-同意；3-驳回；4-转审；5-催办；6-撤销；8-通过后撤销；10-添加备注
    @Override
    public String getStatuChangeEvent() {
        XmlObject approvalInfo = this.approvalInfo();

        return approvalInfo.getChildNodeTextContentByName("StatuChangeEvent");
    }

    private XmlObject approvalInfo() {
        XmlObject _input = Xml.parseString(this.getXml());
        XmlObject xml = _input.getChildNodeByName("xml");
        return xml.getChildNodeByName("ApprovalInfo");
    }

    /**
     * 最后一条 已操作过(同意/拒绝)的 审批流程
     */
    @Override
    public SpRecordDetail getLastSpRecordDetailProcessed() {
        List<SpRecord> spRecords = this.getSpRecords();

        SpRecordDetail lastProcessed = null;

        for (SpRecord spRecord : spRecords) {
            for (SpRecordDetail detail : spRecord.getDetails()) {
                if (!StringUtil.equals("1", detail.getSpStatus())) { // 1 是未操作
                    lastProcessed = detail; // 第一条非1的
                }
            }
        }

        if (null != lastProcessed) {
            return lastProcessed; // 非空
        }

        log.warn("#123 lastProcessed is null, xml=" + this.getXml());
        return null; // 为空
    }

    @Override
    public Integer getSpRecordSize() {
        List<SpRecord> spRecords = this.getSpRecords();
        return null == spRecords ? null : spRecords.size();
    }

    @Override
    public List<SpRecord> getSpRecords() {
        List<SpRecord> spRecordList = new ArrayList<SpRecord>();

        XmlObject approvalInfo = this.approvalInfo();
        XmlObject[] spRecords = approvalInfo.getChildNodeArrayByName("SpRecord");

        Integer index = 0;
        for (XmlObject spRecordXml : spRecords) {
            WebhookSpRecord spRecord = new WebhookSpRecord(spRecordXml);
            spRecord.setIndex(index);
            spRecordList.add(spRecord);

            index++;
        }

        return spRecordList;
    }

    // 全都同意了
    @Override
    public Boolean allAgreed() {
        List<SpRecord> spRecords = this.getSpRecords();

        for (SpRecord spRecord : spRecords) {
            for (SpRecordDetail detail : spRecord.getDetails()) {
                if (!StringUtil.equals("2", detail.getSpStatus()) //
                        && !StringUtil.equals("4", detail.getSpStatus())) { // 1-审批中；2-已同意；3-已驳回；4-已转审
                    log.info("#109 not allAgreed, spRecord=" + spRecord + ", this=" + this);
                    return false;
                }
            }
        }

        // 全都是 同一或转审 没有驳回和未审核
        return true;
    }

    @Override
    public Boolean anyReject() {
        List<SpRecord> spRecords = this.getSpRecords();

        for (SpRecord spRecord : spRecords) {
            for (SpRecordDetail detail : spRecord.getDetails()) {
                if (StringUtil.equals("3", detail.getSpStatus())) { // 1-审批中；2-已同意；3-已驳回；4-已转审
                    log.info("#134 find one reject, spRecord=" + spRecord + ", this=" + this);
                    return true;
                }
            }
        }

        return false;
    }

    @Override
    public List<String> getSpRecordApproverUserIdList() {
        List<SpRecord> spRecords = this.getSpRecords();
        if (null == spRecords) {
            return null;
        }

        List<String> users = new ArrayList<String>();

        for (SpRecord spRecord : spRecords) {
            List<String> approverUserIds = new ArrayList<String>();

            List<SpRecordDetail> details = spRecord.getDetails();
            for (SpRecordDetail detail : details) {
                String approverUserId = detail.getApproverUserId();
                approverUserIds.add(approverUserId);
            }

            users.add(StringUtil.join(approverUserIds, "+")); // 如果同一个节点有多个审批人 就加号拼接
        }

        return users;
    }

    @Override
    public List<Map<String, Object>> getApplyDataMapList() {
        log.error("#200 getApplyDataMapList return null, this=" + this);
        return null;
    }
}